package com.dev.mainual.throwable.base;

import lombok.extern.slf4j.Slf4j;

import java.io.EOFException;
import java.io.IOException;

/**
 * ClassName: ThrowableDemo
 * Description: 基本用法
 * Date: 2019/1/24 14:59 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Slf4j
public class ThrowableDemo {


    public static void test1() {
        int a = 10;
        int b = 0;
        int[] arr = {1, 2, 3};

        System.out.println(a / b);
        System.out.println(arr[3]);

        log.info("这里出现了一个异常，你不太清楚是谁，该怎么办呢 ?");
    }


    /**
     * 多个异常
     * b:写一个try，多个catch
     * try{
     * ...
     * }catch(异常类名 变量名) {
     * ...
     * }
     * catch(异常类名 变量名) {
     * ...
     * }
     * ...
     * <p>
     * 注意事项：
     * 1:能明确的尽量明确，不要用大的来处理。
     * 2:平级关系的异常谁前谁后无所谓，如果出现了子父关系，父必须在后面。
     * <p>
     * 注意：
     * 一旦try里面出了问题，就会在这里把问题给抛出去，然后和catch里面的问题进行匹配，
     * 一旦有匹配的，就执行catch里面的处理，然后结束了try...catch
     * 继续执行后面的语句。
     */
    public static void test2() {

        int a = 10;
        int b = 0;
        int[] arr = {1, 2, 3};

        try {
            System.out.println(a / b);
            System.out.println(arr[3]);
            System.out.println("这里出现了一个异常，你不太清楚是谁，该怎么办呢 ?");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("你访问了不该的访问的索引");
        } catch (Exception e) {
            System.out.println("出问题了");
        }

        // 继续执行
        System.out.println("over");
    }

    /**
     * 格式：try{   }catch(异常名1 | 异常名2 | ... 变量 ) {  }
     */
    public static void test3() {

        int a = 10;
        int b = 0;
        int[] arr = {1, 2, 3};

        try {
            System.out.println(a / b);
            System.out.println(arr[3]);

            log.info("这里出现了一个异常，你不太清楚是谁，该怎么办呢 ?");
        } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
            System.out.println("除数不能为0 | 你访问了不该的访问的索引");
        } catch (Exception e) {
            System.out.println("出问题了");
        }

        // 继续执行
        System.out.println("over");
    }

    /**
     * 如果 catch里面有return语句，请问 finally 里面的代码还会执行吗?
     * 如果会，请问是在return前，还是return后。
     * 答案：会执行。在 return 前执行。
     * <p>
     * 返回 30
     */
    public static int test4() {
        int a = 10;
        try {
            System.out.println(a / 0);
            a = 20;
        } catch (ArithmeticException e) {
            a = 30;
            // 1- return a在程序执行到这一步的时候，这里不是return a而是return 30,这个返回路径就形成了。
            // 2- 发现后面还有finally，所以继续执行finally的内容，a=40
            // 3- 再次回到以前的返回路径，继续走return 30
            return a;
        } finally {
            a = 40;
        }
        return a;
    }

    /**
     * 返回 40
     * finally 如果有return 将覆盖，将会覆盖原来的返回值。不建议使用
     *
     * @return
     */
    public static int test5() {
        int a = 10;
        try {
            System.out.println(a / 0);
            a = 20;
        } catch (ArithmeticException e) {
            a = 30;
            return a;
        } finally {
            a = 40;
            return a;
        }
    }

    public static void test6() throws IOException {

    }

    /**
     * throw 异常对象，正确处理可预见的异常
     *
     * @throws EOFException
     */
    public static void test7() throws EOFException {
        int a = 99;
        for (int i = 0; i < 100; i++) {
            a--;
            if (a < 0) {
                throw new EOFException("发生错误");
            }
        }

    }

    /**
     * 使用自定义异常
     *
     * @throws CusException
     */
    public static void test8() throws CusException {
        int a = 0;
        if (a < 99) {
            throw new CusException("自定义异常");
        }

    }

}
